//
// Created by QU on 24-9-16.
//

// Boost库提供了一些工具来处理网络传输中的字节序问题。网络协议通常使用大端字节序（Big-endian），而大多数现代计算机使用小端字节序（Little-endian）。
// 为了确保在不同平台之间正确传输数据，需要进行字节序转换。
// Boost库中的Boost.Endian库提供了便捷的工具来处理字节序转换。以下是一些常用的函数和用法示例：
// 要使用Boost.Endian库，确保你的Boost库版本在1.58.0或更高，因为Boost.Endian是在这个版本中引入的。

/*
boost::endian::native_to_big: 将本地字节序转换为大端字节序。
boost::endian::big_to_native: 将大端字节序转换为本地字节序。
boost::endian::native_to_little: 将本地字节序转换为小端字节序。
boost::endian::little_to_native: 将小端字节序转换为本地字节序。
*/

// quest: 我可不可以传入一个std::byte[]数组, 我应该怎样使用
// 当然可以处理std::byte[]数组。std::byte是C++17引入的新类型，用于表示原始字节数据。 你可以使用Boost.Endian库来处理数组中的字节序转换。
// 以下是一个示例，展示如何使用Boost.Endian库将一个std::byte[]数组中的数据从本地字节序转换为大端字节序，并进行逆向转换。

// 首先，确保你已经包含了必要的头文件：

#include <iostream>
#include <boost/endian/conversion.hpp>

#include <cstddef>  // for std::byte
#include <cstring>  // for std::memcpy
#include <array>    // for std::array
#include <algorithm> // for std::copy
#include <ranges>

// cpp like (std::copy, std::copy_n, std::ranges::copy(c++20), std::bits(c++20))
void convert_to_big_endian(std::byte* data, std::size_t size)
{
    auto byte_range = std::ranges::subrange(data, data + size);

    /*
     * 下面的for的operator|() 展开是这样的.
    auto chunked_view = std::ranges::views::chunk(byte_range, sizeof(uint32_t));
    for (auto chunk : chunked_view) {
    */

    for (auto chunk : byte_range | std::ranges::views::chunk(sizeof(uint32_t)))
    {
        std::array<std::byte, sizeof(uint32_t)> bytes { };
        std::ranges::copy(chunk, bytes.begin());

        auto value = std::bit_cast<uint32_t>(bytes);
        value = boost::endian::native_to_big(value);
        bytes = std::bit_cast<std::array<std::byte, sizeof(uint32_t)>>(value);

        std::ranges::copy(bytes, chunk.begin());
    }
}

void convert_to_native(std::byte* data, std::size_t size)
{
    auto byte_range = std::ranges::subrange(data, data + size);

    for (auto chunk : byte_range | std::ranges::views::chunk(sizeof(uint32_t)))
    {
        std::array<std::byte, sizeof(uint32_t)> bytes { };
        std::ranges::copy(chunk, bytes.begin());

        auto value = std::bit_cast<uint32_t>(bytes);
        value = boost::endian::big_to_native(value);
        bytes = std::bit_cast<std::array<std::byte, sizeof(uint32_t)>>(value);

        std::ranges::copy(bytes, chunk.begin());
    }
}

// c like
/*
void convert_to_big_endian(std::byte* data, std::size_t size) {
    for (std::size_t i = 0; i < size; i += sizeof(uint32_t)) {
        // 假设数据是以32位块存储的
        uint32_t value;
        std::memcpy(&value, data + i, sizeof(uint32_t));
        value = boost::endian::native_to_big(value);
        std::memcpy(data + i, &value, sizeof(uint32_t));
    }
}

void convert_to_native(std::byte* data, std::size_t size) {
    for (std::size_t i = 0; i < size; i += sizeof(uint32_t)) {
        // 假设数据是以32位块存储的
        uint32_t value;
        std::memcpy(&value, data + i, sizeof(uint32_t));
        value = boost::endian::big_to_native(value);
        std::memcpy(data + i, &value, sizeof(uint32_t));
    }
}
*/

int main()
{
    uint32_t value = 0x12345678;

    // 将本地字节序转换为大端字节序
    uint32_t big_endian_value = boost::endian::native_to_big(value);
    std::cout << "Big-endian: 0x" << std::hex << big_endian_value << std::endl;

    // 将大端字节序转换为本地字节序
    uint32_t native_value = boost::endian::big_to_native(big_endian_value);
    std::cout << "Native: 0x" << std::hex << native_value << std::endl;

    // 将本地字节序转换为小端字节序
    uint32_t little_endian_value = boost::endian::native_to_little(value);
    std::cout << "Little-endian: 0x" << std::hex << little_endian_value << std::endl;

    // 将小端字节序转换为本地字节序
    native_value = boost::endian::little_to_native(little_endian_value);
    std::cout << "Native: 0x" << std::hex << native_value << std::endl;


    ////////////////////////////////////////////////////////////////////////////////////////////

    std::byte data[] = {
        std::byte(0x12), std::byte(0x34), std::byte(0x56), std::byte(0x78),
        std::byte(0x9a), std::byte(0xbc), std::byte(0xde), std::byte(0xf0)
    };

    std::size_t size = sizeof(data) / sizeof(data[0]);

    std::cout << "Original data:" << std::endl;
    for (std::size_t i = 0; i < size; ++i)
    {
        std::cout << std::hex << std::to_integer<int>(data[i]) << " ";
    }
    std::cout << std::endl;

    // 转换为大端字节序
    convert_to_big_endian(data, size);

    std::cout << "Big-endian data:" << std::endl;
    for (std::size_t i = 0; i < size; ++i)
    {
        std::cout << std::hex << std::to_integer<int>(data[i]) << " ";
    }
    std::cout << std::endl;

    // 转换回本地字节序
    convert_to_native(data, size);

    std::cout << "Native data:" << std::endl;
    for (std::size_t i = 0; i < size; ++i)
    {
        std::cout << std::hex << std::to_integer<int>(data[i]) << " ";
    }
    std::cout << std::endl;

    return 0;
}
